﻿using System.Collections.Generic;
using System.Linq;
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Query.SqlExpressions;
using NPOI.SS.Formula.Functions;
using OfficeOpenXml;
using OfficeOpenXml.FormulaParsing.Excel.Functions.DateTime;
using OfficeOpenXml.FormulaParsing.Excel.Functions.Logical;
using OfficeOpenXml.Style;
using Simple.Common.Extensions;
using Simple.Repository.Models.Attendance;
using Simple.Repository.Models.ClassRoom;
using Simple.Services.System.FileInfo.Models;
using Simple.Services.System.Office;

namespace Simple.Services.System.ClassRoom
{
    public class StaffAttendanceRuleService : BusinessBaseService
    {
        private readonly SimpleDbContext _context;
        private readonly CacheService _cacheService;
        private readonly ExcelOperationService _excelOperationService;


        public StaffAttendanceRuleService(SimpleDbContext context,
                           ISimpleService services,
                           CacheService cacheService,
                           ExcelOperationService excelOperationService) : base(services)
        {
            _context = context;
            _cacheService = cacheService;
            _excelOperationService = excelOperationService;
        }

        public async Task<StaffAttendanceRuleOutputModel> GetAsync(Guid? Id)
        {
            if (!Id.HasValue)
            {
                throw AppResultException.Status409Conflict("参数错误,请选择考勤组进行查询!");
            }

            var staffAttendanceRuleInfo = await _context.Set<StaffAttendanceRule>().FirstOrDefaultAsync(c => c.Id == Id);

            if (staffAttendanceRuleInfo == null)
            {
                throw AppResultException.Status409Conflict("未找到考勤组相关数据!");
            }

            var outResult = MapperHelper.Map<StaffAttendanceRuleOutputModel>(staffAttendanceRuleInfo);
            return outResult;
        }

        public async Task<PageResultModel<StaffAttendanceRuleOutputModel>> GetPageAsync(StaffAttendanceRuleQueryPageInputModel input)
        {
            var result = new PageResultModel<StaffAttendanceRuleOutputModel>();
            var query = await OrganizationFilter(_context.Set<StaffAttendanceRule>().Include(c => c.Users).Include(p => p.CycleSettings));

            // 根据条件查询
            if (!string.IsNullOrEmpty(input.Name))
            {
                query = query.Where(m => EF.Functions.Like(m.Name, $"%{input.Name}%"));
            }

            // 排序
            query = query.OrderByDescending(m => m.CreatedTime);

            // 获取总数量
            result.TotalRows = await query.CountAsync();

            // 分页查询
            query = query.Page(input.PageNo, input.PageSize);
            var staffAttendanceRuleList = await query.ToListAsync();
            result.Rows = MapperHelper.Map<List<StaffAttendanceRuleOutputModel>>(staffAttendanceRuleList);

            result.SetPage(input);
            result.CountTotalPage();

            return result;
        }

        public async Task<int> AddAsync(StaffAttendanceRuleOutputModel model)
        {
            if (await _context.Set<StaffAttendanceRule>().AnyAsync(m => m.Name == model.Name))
            {
                throw AppResultException.Status409Conflict("已存在相同名称的考勤组，请重新填写！");
            }

            List<Guid>? inputUserIdList = null;
            var settingUserList = (await OrganizationFilter(_context.Set<StaffAttendanceUser>()))?.ToList();
            if (settingUserList != null && settingUserList.Any())
            {
                inputUserIdList = model.Users?.Select(c => c.UserId)?.ToList();
                if (inputUserIdList == null || !inputUserIdList.Any())
                {
                    throw AppResultException.Status409Conflict("请选择考勤组人员！");
                }
            }

            if (inputUserIdList != null && inputUserIdList.Any() && (settingUserList?.Any(c => inputUserIdList.Contains(c.UserId)) ?? false))
            {
                var userNames = settingUserList?.Where(c => inputUserIdList.Contains(c.UserId))?.Select(c => c.UserName);
                throw AppResultException.Status409Conflict($"员工:{string.Join(",", userNames)}只能归属一个考勤组，请重新选择人员！");
            }

            var staffAttendanceRule = MapperHelper.Map<StaffAttendanceRule>(model);
            await _context.AddAsync(staffAttendanceRule);
            return await _context.SaveChangesAsync();
        }

        public async Task<int> UpdateAsync(StaffAttendanceRuleOutputModel model)
        {
            if (!model.Id.HasValue)
            {
                throw AppResultException.Status409Conflict("参数错误,考勤组参数不能为Null!");
            }

            if (await _context.Set<StaffAttendanceRule>().AnyAsync(m => m.Name == model.Name && m.Id != model.Id))
            {
                throw AppResultException.Status409Conflict("已存在相同名称的考勤组，请重新填写！");
            }

            var staffAttendanceRuleInfo = await _context.Set<StaffAttendanceRule>().Include(c => c.CycleSettings).Include(c => c.Users)
                .Where(m => model.Id == m.Id)
                .FirstOrDefaultAsync();

            if (staffAttendanceRuleInfo == null)
            {
                throw AppResultException.Status404NotFound("未找到考勤组相关数据，更新失败！");
            }

            List<Guid>? inputUserIdList = null;
            var settingUserList = (await OrganizationFilter(_context.Set<StaffAttendanceUser>()))?.ToList();
            if (settingUserList != null && settingUserList.Any())
            {
                inputUserIdList = model.Users?.Select(c => c.UserId)?.ToList();
                if (inputUserIdList == null || !inputUserIdList.Any())
                {
                    throw AppResultException.Status409Conflict("请选择考勤组员工！");
                }
            }

            if (inputUserIdList != null && inputUserIdList.Any() && (settingUserList?.Any(c => inputUserIdList.Contains(c.UserId)) ?? false))
            {
                var staffAttendanceUserList = settingUserList?.Where(c => inputUserIdList.Contains(c.UserId));
                if (staffAttendanceUserList != null && staffAttendanceUserList.Any())
                {
                    var notStaffAttendanceUserList = staffAttendanceUserList?.Where(c => c.StaffAttendanceRuleId != staffAttendanceRuleInfo.Id)?.ToList();
                    if (notStaffAttendanceUserList != null && notStaffAttendanceUserList.Any())
                    {
                        var notStaffAttendanceUserIdList = notStaffAttendanceUserList?.Select(c => c.UserId);
                        var userNames = settingUserList?.Where(c => notStaffAttendanceUserIdList?.Contains(c.UserId) ?? false)?.Select(c => c.UserName);
                        throw AppResultException.Status409Conflict($"员工:{string.Join(",", userNames)}只能归属一个考勤组，请重新选择员工！");
                    }
                }
            }

            MapperHelper.Map(model, staffAttendanceRuleInfo);
            _context.Update(staffAttendanceRuleInfo);
            int ret = await _context.SaveChangesAsync();

            if (ret == 0)
            {
                throw AppResultException.Status200OK("更新记录数为0");
            }

            return ret;
        }

        public async Task<int> DeleteAsync(List<Guid?> ids)
        {
            if (ids == null || !ids.Any())
            {
                throw AppResultException.Status409Conflict("参数错误,请选择要删除的考勤组!");
            }

            var staffAttendanceRuleList = await _context.Set<StaffAttendanceRule>().Include(c => c.CycleSettings).Include(c => c.Users)
                .Where(m => ids.Contains(m.Id))
                .ToListAsync();

            if (staffAttendanceRuleList == null || !staffAttendanceRuleList.Any())
            {
                throw AppResultException.Status404NotFound("未找到考勤组相关数据，删除失败！");
            }

            if (staffAttendanceRuleList.Any(c => c.Users.Any()))
            {
                throw AppResultException.Status404NotFound("存在考勤组关联人员考勤数据，请联系管理员后再试！");
            }

            // 先更新数据库
            _context.RemoveRange(staffAttendanceRuleList);
            int ret = await _context.SaveChangesAsync();
            if (ret == 0)
            {
                throw AppResultException.Status200OK("更新记录数为0");
            }

            return ret;
        }

        /// <summary>
        /// 员工考勤统计
        /// </summary>
        /// <param name="input"></param>
        /// <returns></returns>
        public async Task<PageResultModel<StaffAttendanceStatisticsReportOutputModel>> GetStaffAttendanceRecord(StaffAttendanceStatisticsReportInputModel input)
        {
            var result = new PageResultModel<StaffAttendanceStatisticsReportOutputModel>();
            var userQuery = _context.Set<SysUser>().AsQueryable();

            var organQuery = _context.Set<SysOrganization>().AsQueryable();
            // 根据条件查询
            if (input.OrganizationId.HasValue)
            {
                userQuery = userQuery.Where(u => u.OrganizationId == input.OrganizationId);
            }
            else
            {
                if (!_currentUser.IsSuperAdmin)
                {
                    userQuery = userQuery.Where(u => u.OrganizationId == _currentUser.OrganizationId);
                }
            }

            if (!string.IsNullOrEmpty(input.Name))
            {
                userQuery = userQuery.Where(u => EF.Functions.Like(u.UserName, $"%{input.Name}%") ||
                                         EF.Functions.Like(u.Name!, $"%{input.Name}%"));
            }

            // 获取总数量
            result.TotalRows = await userQuery.CountAsync();
            userQuery = userQuery.Page(input.PageNo, input.PageSize);


            var attendanceRecordQuery = _context.Set<AttendanceRecord>().AsQueryable();
            if (input.Date.HasValue)
            {
                var startDate = DateTime.Parse(input.Date.Value.ToString("yyyy-MM-01 00:00:00"));
                var v = $"{input.Date.Value.Year}-{input.Date.Value.Month}-{$"{DateTime.DaysInMonth(input.Date.Value.Year, input.Date.Value.Month)}".PadLeft(2, '0')} 23:59:59";
                var endDate = DateTime.Parse(v.Trim());
                attendanceRecordQuery = attendanceRecordQuery.Where(u => u.AttendanceTime >= startDate && u.AttendanceTime <= endDate);
            }

            var query = from u in userQuery
                        join org in organQuery on u.OrganizationId equals org.Id into utemp
                        from up in utemp.DefaultIfEmpty()
                        join ar in attendanceRecordQuery on u.UserName equals ar.UserNumber into temp
                        from tp in temp.DefaultIfEmpty()
                        select new StaffAttendanceRecordOutputModel
                        {
                            UserId = u.Id,
                            UserName = u.Name,
                            OrganizationId = up.Id,
                            OrganizationName = up.Name,
                            ClockingTime = tp.AttendanceTime,
                            UserNumber = tp.UserNumber
                        };


            var staffAttendanceAllRecord = await query.ToListAsync();
            var currentResult = new List<StaffAttendanceStatisticsReportOutputModel>();
            if (staffAttendanceAllRecord != null && staffAttendanceAllRecord.Any())
            {
                var hhp = HolidayHelper.GetInstance();
                var holidayAndWorkList = hhp.GetWorkDayByTime(input.Date.Value);//国家法定节假日和工作日
                var staffAttendanceRule = (await OrganizationFilter(_context.Set<StaffAttendanceRule>().Include(c => c.Users).Include(c => c.CycleSettings)))?.ToList();// 考勤规则

                var gourpStaffAttendance = staffAttendanceAllRecord.GroupBy(c => c.UserId)?.ToDictionary(c => c.Key, c => c.Select(p => p)?.ToList());

                foreach (var item in gourpStaffAttendance)
                {
                    var model = new StaffAttendanceStatisticsReportOutputModel();
                    var otherInfo = item.Value?.FirstOrDefault();
                    model.UserId = item.Key;
                    model.UserName = otherInfo?.UserName ?? string.Empty;
                    model.OrganizationName = otherInfo?.OrganizationName ?? string.Empty;
                    model.OrganizationId = otherInfo?.OrganizationId;
                    var due = 0;// 应出
                    var notSignedIn = 0; // 未签到
                    var actualOutput = 0;// 实际出勤（不包含早退、迟到）
                    var days = DateTime.DaysInMonth(input.Date.Value.Year, input.Date.Value.Month);
                    var rule = staffAttendanceRule?.FirstOrDefault(c => c.Users.Any(p => p.UserId == item.Key));
                    var cycleALL = rule?.CycleSettings?.Select(c => c.PeriodType.GetHashCode()) ?? new List<int>();

                    var _currentRealityDate = new List<DateTime>();//结合考勤规则本月应出日期
                    if (rule != null && rule.IsExcludingLegalHolidays)
                    {
                        //自动排休（法定工作日=应出，法定工作日中剔除规则配置中的周六周日选项，还要剔除未勾选的考勤周期选项）
                        for (var i = 1; i <= days; i++)
                        {
                            DateTime currtime = DateTime.Parse($"{input.Date.Value.Year}-{(input.Date.Value.Month).ToString().PadLeft(2, '0')}-{i.ToString().PadLeft(2, '0')}");
                            int week = (int)currtime.DayOfWeek;

                            if (cycleALL != null && cycleALL.Any(c => week == c))
                            {
                                _currentRealityDate.Add(currtime);
                                due++;
                            }
                        }
                    }
                    else if (rule != null && !rule.IsExcludingLegalHolidays)
                    {
                        //不自动排休
                        for (var i = 1; i <= days; i++)
                        {
                            DateTime currtime = DateTime.Parse($"{input.Date.Value.Year}-{(input.Date.Value.Month).ToString().PadLeft(2, '0')}-{i.ToString().PadLeft(2, '0')}");
                            int week = (int)currtime.DayOfWeek;

                            if (cycleALL != null && cycleALL.Any(c => week == c))
                            {
                                _currentRealityDate.Add(currtime);
                                due++;
                            }
                        }
                    }

                    _currentRealityDate = _currentRealityDate.OrderBy(c => c).ToList();
                    if (_currentRealityDate == null || !_currentRealityDate.Any())
                    {
                        _currentRealityDate = holidayAndWorkList.Item1;
                    }

                    var recordDate = item.Value?.Where(c => c.ClockingTime.HasValue).OrderBy(c => c.ClockingTime)?.Select(c => c.ClockingTime).ToList();
                    if (recordDate != null && recordDate.Any())
                    {
                        foreach (var realityDate in _currentRealityDate)
                        {
                            var firstDateTime = DateTime.Parse($"{realityDate.Year}-{(realityDate.Month).ToString().PadLeft(2, '0')}-{realityDate.Day.ToString().PadLeft(2, '0')} {rule?.StartTime ?? "08:30"}");// 规则设置中最早打卡时间
                            var lastDateTime = DateTime.Parse($"{realityDate.Year}-{(realityDate.Month).ToString().PadLeft(2, '0')}-{realityDate.Day.ToString().PadLeft(2, '0')} {rule?.EndTime ?? "17:30"}"); //规则设置中最晚打卡时间
                            var _currentRecordDate = recordDate.Where(c => c.Value.Year == realityDate.Year && c.Value.Month == realityDate.Month && c.Value.Day == realityDate.Day)?.OrderBy(c => c.Value);
                            if (_currentRecordDate != null && _currentRecordDate.Any())
                            {
                                var _firstDate = _currentRecordDate.FirstOrDefault();
                                var _lastDate = _currentRecordDate.LastOrDefault();
                                if (firstDateTime >= _firstDate && _lastDate >= lastDateTime)
                                {
                                    // 有效打卡
                                    actualOutput++;
                                }
                                else
                                {
                                    // 无效打卡（迟到、早退）
                                }
                            }
                            else
                            {
                                //缺卡
                                notSignedIn++;
                            }
                        }
                    }


                    model.NotSignedIn = notSignedIn;
                    model.Due = due;
                    model.ActualOutput = actualOutput;
                    currentResult.Add(model);
                }
            }

            // 获取总数量
            result.Rows = currentResult;
            result.SetPage(input);
            result.CountTotalPage();

            return result;
        }


        /// <summary>
        /// 根据人员Id查询某月考勤记录
        /// </summary>
        /// <param name="input"></param>
        /// <returns></returns>
        public async Task<List<StaffAttendanceRecordOutputModel2>> GetStaffAttendanceRecordByUserId(StaffAttendanceRecordByUserIdInputModel input)
        {
            var result = new List<StaffAttendanceRecordOutputModel2>();
            var userQuery = _context.Set<SysUser>().Where(c => c.Id == input.UserId);
            var attendanceRecordQuery = _context.Set<AttendanceRecord>().AsQueryable();
            if (input.Date.HasValue)
            {
                var startDate = DateTime.Parse(input.Date.Value.ToString("yyyy-MM-01 00:00:00"));
                var v = $"{input.Date.Value.Year}-{input.Date.Value.Month}-{$"{DateTime.DaysInMonth(input.Date.Value.Year, input.Date.Value.Month)}".PadLeft(2, '0')} 23:59:59";
                var endDate = DateTime.Parse(v.Trim());
                attendanceRecordQuery = attendanceRecordQuery.Where(u => u.AttendanceTime >= startDate && u.AttendanceTime <= endDate);
            }

            var query = from u in userQuery
                        join ar in attendanceRecordQuery on u.UserName equals ar.UserNumber into temp
                        from tp in temp.DefaultIfEmpty()
                        select new StaffAttendanceRecordOutputModel
                        {
                            UserId = u.Id,
                            UserName = u.Name,
                            ClockingTime = tp.AttendanceTime,
                            UserNumber = tp.UserNumber,
                            EntranceType = tp.EntranceType,
                        };


            var staffAttendanceAllRecord = await query.OrderBy(c => c.ClockingTime).ToListAsync();
            if (staffAttendanceAllRecord != null && staffAttendanceAllRecord.Any())
            {
                var hhp = HolidayHelper.GetInstance();
                var holidayAndWorkList = hhp.GetWorkDayByTime(input.Date.Value);//国家法定节假日和工作日
                var staffAttendanceRule = (await OrganizationFilter(_context.Set<StaffAttendanceRule>().Include(c => c.Users).Include(c => c.CycleSettings)))?.ToList();// 考勤规则

                var days = DateTime.DaysInMonth(input.Date.Value.Year, input.Date.Value.Month);
                var rule = staffAttendanceRule?.FirstOrDefault(c => c.Users.Any(p => p.UserId == input.UserId));
                var cycleALL = rule?.CycleSettings?.Select(c => c.PeriodType.GetHashCode()) ?? new List<int>();

                var _currentRealityDate = new List<DateTime>();//结合考勤规则本月应出日期
                if (rule != null && rule.IsExcludingLegalHolidays)
                {
                    //自动排休（法定工作日=应出，法定工作日中剔除规则配置中的周六周日选项，还要剔除未勾选的考勤周期选项）
                    for (var i = 1; i <= days; i++)
                    {
                        DateTime currtime = DateTime.Parse($"{input.Date.Value.Year}-{(input.Date.Value.Month).ToString().PadLeft(2, '0')}-{i.ToString().PadLeft(2, '0')}");
                        int week = (int)currtime.DayOfWeek;

                        if (cycleALL != null && cycleALL.Any(c => week == c))
                        {
                            _currentRealityDate.Add(currtime);
                        }
                    }
                }
                else if (rule != null && !rule.IsExcludingLegalHolidays)
                {
                    //不自动排休
                    for (var i = 1; i <= days; i++)
                    {
                        DateTime currtime = DateTime.Parse($"{input.Date.Value.Year}-{(input.Date.Value.Month).ToString().PadLeft(2, '0')}-{i.ToString().PadLeft(2, '0')}");
                        int week = (int)currtime.DayOfWeek;

                        if (cycleALL != null && cycleALL.Any(c => week == c))
                        {
                            _currentRealityDate.Add(currtime);
                        }
                    }
                }

                _currentRealityDate = _currentRealityDate.OrderBy(c => c).ToList();
                if (_currentRealityDate == null || !_currentRealityDate.Any())
                {
                    _currentRealityDate = holidayAndWorkList.Item1;
                }

                for (var i = 1; i <= days; i++)
                {
                    DateTime currtime = DateTime.Parse($"{input.Date.Value.Year}-{(input.Date.Value.Month).ToString().PadLeft(2, '0')}-{i.ToString().PadLeft(2, '0')}");
                    if ((DateTime.Now - currtime).TotalDays >= 0)
                    {
                        var currentClockingTimes = staffAttendanceAllRecord.Where(c => c.ClockingTime.HasValue && c.ClockingTime.Value.Year == currtime.Year && c.ClockingTime.Value.Month == currtime.Month && c.ClockingTime.Value.Day == currtime.Day).OrderBy(c => c.ClockingTime);
                        if (_currentRealityDate.Any(c => c.Year == currtime.Year && c.Month == currtime.Month && c.Day == currtime.Day))
                        {
                            var firstDateTime = DateTime.Parse($"{currtime.Year}-{(currtime.Month).ToString().PadLeft(2, '0')}-{currtime.Day.ToString().PadLeft(2, '0')} {rule?.StartTime ?? "08:30"}");// 规则设置中最早打卡时间
                            var lastDateTime = DateTime.Parse($"{currtime.Year}-{(currtime.Month).ToString().PadLeft(2, '0')}-{currtime.Day.ToString().PadLeft(2, '0')} {rule?.EndTime ?? "17:30"}"); //规则设置中最晚打卡时间

                            //应出勤日
                            if (currentClockingTimes != null && currentClockingTimes.Any())
                            {
                                var shangbanTitle = "缺卡";
                                var startTime = currentClockingTimes.OrderBy(x => x.ClockingTime).FirstOrDefault(x => x.EntranceType == 1)?.ClockingTime;
                                if (startTime != null)
                                {
                                    shangbanTitle = $"{startTime.Value.ToString("HH:mm:ss")} {(startTime > firstDateTime ? "迟到" : "")}";
                                }
                                //上班
                                result.Add(new StaffAttendanceRecordOutputModel2
                                {
                                    Title = shangbanTitle,
                                    Start = $"{currtime.ToString("yyyy-MM-dd")}",
                                    End = $"{currtime.ToString("yyyy-MM-dd")}",
                                    CssClass = "'red'"
                                });

                                var xiabanTitle = "缺卡";
                                var endtime = currentClockingTimes.OrderByDescending(x => x.ClockingTime).FirstOrDefault(x => x.EntranceType == 2)?.ClockingTime;
                                if (endtime != null)
                                {
                                    xiabanTitle = $"{endtime.Value.ToString("HH:mm:ss")} {(endtime < lastDateTime ? "早退" : "")}";
                                }
                                //下班
                                result.Add(new StaffAttendanceRecordOutputModel2
                                {
                                    Title = xiabanTitle,
                                    Start = $"{currtime.ToString("yyyy-MM-dd")}",
                                    End = $"{currtime.ToString("yyyy-MM-dd")}",
                                    CssClass = "'red'"
                                });
                            }
                            else
                            {
                                //上班
                                result.Add(new StaffAttendanceRecordOutputModel2
                                {
                                    Title = $"缺卡",
                                    Start = $"{currtime.ToString("yyyy-MM-dd")}",
                                    End = $"{currtime.ToString("yyyy-MM-dd")}",
                                    CssClass = "'red'"
                                });

                                //下班
                                result.Add(new StaffAttendanceRecordOutputModel2
                                {
                                    Title = $"缺卡",
                                    Start = $"{currtime.ToString("yyyy-MM-dd")}",
                                    End = $"{currtime.ToString("yyyy-MM-dd")}",
                                    CssClass = "'red'"
                                });
                            }
                        }
                    }
                }
            }

            return result;
        }


        /// <summary>
        /// 根据人员Id查询某月考勤记录(移动端)
        /// </summary>
        /// <param name="input"></param>
        /// <returns></returns>
        public async Task<List<MoveStaffAttendanceRecordOutputModel>> GetMoveStaffAttendanceRecordByUserId(StaffAttendanceRecordByUserIdInputModel input)
        {
            var result = new List<MoveStaffAttendanceRecordOutputModel>();
            var userQuery = _context.Set<SysUser>().Where(c => c.Id == input.UserId);
            var attendanceRecordQuery = _context.Set<AttendanceRecord>().AsQueryable();
            if (input.Date.HasValue)
            {
                var startDate = DateTime.Parse(input.Date.Value.ToString("yyyy-MM-01 00:00:00"));
                var v = $"{input.Date.Value.Year}-{input.Date.Value.Month}-{$"{DateTime.DaysInMonth(input.Date.Value.Year, input.Date.Value.Month)}".PadLeft(2, '0')} 23:59:59";
                var endDate = DateTime.Parse(v.Trim());
                attendanceRecordQuery = attendanceRecordQuery.Where(u => u.AttendanceTime >= startDate && u.AttendanceTime <= endDate);
            }

            var query = from u in userQuery
                        join ar in attendanceRecordQuery on u.UserName equals ar.UserNumber into temp
                        from tp in temp.DefaultIfEmpty()
                        select new StaffAttendanceRecordOutputModel
                        {
                            UserId = u.Id,
                            UserName = u.Name,
                            ClockingTime = tp.AttendanceTime,
                            UserNumber = tp.UserNumber,
                            EntranceType = tp.EntranceType
                        };


            var staffAttendanceAllRecord = await query.OrderBy(c => c.ClockingTime).ToListAsync();
            if (staffAttendanceAllRecord != null && staffAttendanceAllRecord.Any())
            {
                var hhp = HolidayHelper.GetInstance();
                var holidayAndWorkList = hhp.GetWorkDayByTime(input.Date.Value);//国家法定节假日和工作日
                var staffAttendanceRule = (await OrganizationFilter(_context.Set<StaffAttendanceRule>().Include(c => c.Users).Include(c => c.CycleSettings)))?.ToList();// 考勤规则

                var days = DateTime.DaysInMonth(input.Date.Value.Year, input.Date.Value.Month);
                var rule = staffAttendanceRule?.FirstOrDefault(c => c.Users.Any(p => p.UserId == input.UserId));
                var cycleALL = rule?.CycleSettings?.Select(c => c.PeriodType.GetHashCode()) ?? new List<int>();

                var _currentRealityDate = new List<DateTime>();//结合考勤规则本月应出日期
                if (rule != null && rule.IsExcludingLegalHolidays)
                {
                    //自动排休（法定工作日=应出，法定工作日中剔除规则配置中的周六周日选项，还要剔除未勾选的考勤周期选项）
                    for (var i = 1; i <= days; i++)
                    {
                        DateTime currtime = DateTime.Parse($"{input.Date.Value.Year}-{(input.Date.Value.Month).ToString().PadLeft(2, '0')}-{i.ToString().PadLeft(2, '0')}");
                        int week = (int)currtime.DayOfWeek;

                        if (cycleALL != null && cycleALL.Any(c => week == c))
                        {
                            _currentRealityDate.Add(currtime);
                        }
                    }
                }
                else if (rule != null && !rule.IsExcludingLegalHolidays)
                {
                    //不自动排休
                    for (var i = 1; i <= days; i++)
                    {
                        DateTime currtime = DateTime.Parse($"{input.Date.Value.Year}-{(input.Date.Value.Month).ToString().PadLeft(2, '0')}-{i.ToString().PadLeft(2, '0')}");
                        int week = (int)currtime.DayOfWeek;

                        if (cycleALL != null && cycleALL.Any(c => week == c))
                        {
                            _currentRealityDate.Add(currtime);
                        }
                    }
                }

                _currentRealityDate = _currentRealityDate.OrderBy(c => c).ToList();
                if (_currentRealityDate == null || !_currentRealityDate.Any())
                {
                    _currentRealityDate = holidayAndWorkList.Item1;
                }

                for (var i = 1; i <= days; i++)
                {
                    DateTime currtime = DateTime.Parse($"{input.Date.Value.Year}-{(input.Date.Value.Month).ToString().PadLeft(2, '0')}-{i.ToString().PadLeft(2, '0')}");
                    if ((DateTime.Now - currtime).TotalDays >= 0)
                    {
                        var currentClockingTimes = staffAttendanceAllRecord.Where(c => c.ClockingTime.HasValue && c.ClockingTime.Value.Year == currtime.Year && c.ClockingTime.Value.Month == currtime.Month && c.ClockingTime.Value.Day == currtime.Day).OrderBy(c => c.ClockingTime);
                        if (_currentRealityDate.Any(c => c.Year == currtime.Year && c.Month == currtime.Month && c.Day == currtime.Day))
                        {
                            var firstDateTime = DateTime.Parse($"{currtime.Year}-{(currtime.Month).ToString().PadLeft(2, '0')}-{currtime.Day.ToString().PadLeft(2, '0')} {rule?.StartTime ?? "08:30"}");// 规则设置中最早打卡时间
                            var lastDateTime = DateTime.Parse($"{currtime.Year}-{(currtime.Month).ToString().PadLeft(2, '0')}-{currtime.Day.ToString().PadLeft(2, '0')} {rule?.EndTime ?? "17:30"}"); //规则设置中最晚打卡时间

                            //应出勤日
                            if (currentClockingTimes != null && currentClockingTimes.Any())
                            {
                                //应出勤日
                                if (currentClockingTimes != null && currentClockingTimes.Any())
                                {
                                    var data = new MoveStaffAttendanceRecordOutputModel();
                                    data.Date = $"{currtime.ToString("yyyy-MM-dd")}";
                                    var startTime = currentClockingTimes.FirstOrDefault(x => x.EntranceType == 1)?.ClockingTime;
                                    if (startTime != null)
                                    {
                                        data.Data.Shangbanka = $"{startTime.Value.ToString("HH:mm:ss")} {(startTime > firstDateTime ? "迟到" : "")}";
                                    }
                                    else
                                    {
                                        data.Data.Shangbanka = "缺卡";
                                    }

                                    var endtime = currentClockingTimes.FirstOrDefault(x => x.EntranceType == 2)?.ClockingTime;
                                    if (endtime != null)
                                    {
                                        data.Data.Xiabanka = $"{endtime.Value.ToString("HH:mm:ss")} {(endtime < lastDateTime ? "早退" : "")}";
                                    }
                                    else
                                    {
                                        data.Data.Xiabanka = "缺卡";
                                    }
                                    result.Add(data);
                                }
                            }
                            else
                            {
                                result.Add(new MoveStaffAttendanceRecordOutputModel
                                {
                                    Date = $"{currtime.ToString("yyyy-MM-dd")}",
                                    Info = $"未签到",
                                    Data = new StaffAttendanceData { Xiabanka = $"", Shangbanka = $"" }
                                });
                            }
                        }
                    }
                }
            }

            return result;
        }

        /// <summary>
        /// 每日考勤统计情况
        /// </summary>
        /// <param name="input"></param>
        /// <returns></returns>
        public async Task<MoveStaffAttendanceRecordStatisticsOutputModel> GetStaffAttendanceRecordStatistics(MoveStaffAttendanceRecordInputModel input)
        {
            // 当前登录人的机构 （递归取得顶级机构后再次递归取得当前机构下所有部门）
            var orgId = _currentUser.OrganizationId;
            var currentOrgs = new List<SysOrganization>();
            var sysOrganizations = await _context.Set<SysOrganization>().ToListAsync();
            var currentOrg = sysOrganizations.FirstOrDefault(c => c.Id == orgId);
            SysOrganization topOrg = null;
            List<SysOrganization> currentChildOrgs = null;
            GetTopOrganInfo(sysOrganizations, currentOrg, ref topOrg);
            if (topOrg != null)
            {
                // 递归获取子级机构
                GetChildOrganInfo(sysOrganizations, topOrg.Id, ref currentChildOrgs);
            }

            if (currentChildOrgs == null)
            {
                currentChildOrgs = new List<SysOrganization>();
            }

            currentChildOrgs.Add(topOrg);

            var result = new MoveStaffAttendanceRecordStatisticsOutputModel();
            DateTime currtime = DateTime.Parse($"{input.Date.Value.Year}-{(input.Date.Value.Month).ToString().PadLeft(2, '0')}-{(input.Date.Value.Day).ToString().PadLeft(2, '0')}");
            int week = (int)currtime.DayOfWeek;
            result.Date = $"{currtime.ToString("yyyy-MM-dd")} {((PeriodType)Enum.Parse(typeof(PeriodType), week.ToString())).GetEnumDescription()}";
            DateTime.TryParse(currtime.ToString("yyyy-MM-dd 00:00:00"), out var startTime);
            DateTime.TryParse(currtime.ToString("yyyy-MM-dd 23:59:59"), out var endTime);
            //当天打卡记录
            var staffAttendanceRecordQuery = from c in _context.Set<AttendanceRecord>()
                                             where c.AttendanceTime >= startTime && c.AttendanceTime <= endTime
                                             select new
                                             {
                                                 c.AttendanceTime,
                                                 c.UserId,
                                                 c.AttendanceType,
                                                 c.UserNumber
                                             };
            var staffAttendanceRecord = await staffAttendanceRecordQuery.ToListAsync();

            var ruleQuery = from c in _context.Set<StaffAttendanceRule>()
                            join a in _context.Set<StaffAttendanceUser>() on c.Id equals a.StaffAttendanceRuleId into tp2
                            from tu in tp2.DefaultIfEmpty()
                            join u in _context.Set<SysUser>() on tu.UserId equals u.Id into tp3
                            from ts in tp3
                            join b in _context.Set<StaffAttendanceCycle>() on c.Id equals b.StaffAttendanceRuleId into tp
                            from tc in tp
                            where tc.PeriodType == week
                            select new
                            {
                                c.Id,
                                c.IsExcludingLegalHolidays,
                                c.StartTime,
                                c.EndTime,
                                c.Name,
                                User = tu,
                                Cycle = tc,
                                SysUser = ts
                            };
            var ruleAll = await ruleQuery.ToListAsync();
            // 当天应考勤的人数
            var currentRuleAll = ruleAll.GroupBy(c => new { c.Id, c.EndTime, c.StartTime, c.IsExcludingLegalHolidays, c.Name }).Select(p => new { Id = p.Key.Id, EndTime = p.Key.EndTime, StartTime = p.Key.StartTime, IsExcludingLegalHolidays = p.Key.IsExcludingLegalHolidays, Name = p.Key.Name, Users = p.Where(c => c.Id == p.Key.Id)?.Select(c => c.User), Cycles = p.Where(c => c.Id == p.Key.Id)?.Select(c => c.Cycle) });
            var currentAttendanceUserIds = currentRuleAll.SelectMany(c => c.Users)?.Select(c => c.UserId);

            var userNameList = ruleAll.Select(x => x.SysUser.UserName).ToList();

            //上午打卡人数 12:00:00之前
            DateTime.TryParse(currtime.ToString("yyyy-MM-dd 12:00:00"), out var endDateTime);
            //下午打卡人数 12：00之后23:59:59之前
            DateTime.TryParse(currtime.ToString("yyyy-MM-dd 23:59:59"), out var endDateTime2);
            var shangwuAttendanceRecord = staffAttendanceRecord?.Where(c => c.AttendanceTime <= endDateTime && c.AttendanceType == 1 && userNameList.Contains(c.UserNumber))?.ToList();
            var xiawuAttendanceRecord = staffAttendanceRecord?.Where(c => c.AttendanceTime >= endDateTime && c.AttendanceTime <= endDateTime2 && c.AttendanceType == 1 && userNameList.Contains(c.UserNumber))?.ToList();
            result.Morning = new MoveStaffAttendanceRecordDeptStatisticsOutputModel();
            var swUserRecord = shangwuAttendanceRecord?.GroupBy(c => c.UserNumber)?.ToDictionary(c => c.Key, c => c.Select(p => p));
            var xwUserRecord = xiawuAttendanceRecord?.GroupBy(c => c.UserNumber)?.ToDictionary(c => c.Key, c => c.Select(p => p));
            result.Morning.ClockTotal = swUserRecord?.Count ?? 0;
            result.Morning.Total = currentAttendanceUserIds?.Count() ?? 0;
            result.Morning.LateTotal = 0;
            result.Morning.RecordDetails = new List<MoveStaffAttendanceRecordDetailsDeptOutputModel>();

            result.Night = new MoveStaffAttendanceRecordDeptStatisticsOutputModel();
            result.Night.ClockTotal = xwUserRecord?.Count ?? 0;
            result.Night.Total = currentAttendanceUserIds?.Count() ?? 0;
            result.Night.LateTotal = 0;
            result.Night.RecordDetails = new List<MoveStaffAttendanceRecordDetailsDeptOutputModel>();

            var orgIdList = currentChildOrgs?.Select(c => c.Id).ToList();
            var sysUsers = _context.Set<SysUser>().Where(c => orgIdList.Contains(c.OrganizationId.Value))?.ToList();
            currentChildOrgs = currentChildOrgs?.OrderBy(c => c.CreatedTime)?.ToList();
            foreach (var dept in currentChildOrgs)
            {
                var deptUserList = sysUsers?.Where(c => c.OrganizationId == dept.Id && (currentAttendanceUserIds?.Contains(c.Id) ?? false));//部门参与考勤人数
                var _item = new MoveStaffAttendanceRecordDetailsDeptOutputModel();
                _item.Total = deptUserList?.Count() ?? 0;
                _item.DeptId = dept.Id;
                _item.DeptName = dept.Name;
                _item.PuncherTotal = swUserRecord?.Where(c => deptUserList?.Any(p => p.UserName == c.Key) ?? false)?.Count() ?? 0;
                _item.LateOrleaveEarly = 0;

                var _item2 = new MoveStaffAttendanceRecordDetailsDeptOutputModel();
                _item2.Total = deptUserList?.Count() ?? 0;
                _item2.DeptId = dept.Id;
                _item2.DeptName = dept.Name;
                _item2.PuncherTotal = xwUserRecord?.Where(c => deptUserList?.Any(p => p.UserName == c.Key) ?? false)?.Count() ?? 0;
                _item2.LateOrleaveEarly = 0;
                foreach (var user in deptUserList)
                {
                    var rule = currentRuleAll?.FirstOrDefault(c => c.Users.Any(p => p.UserId == user.Id));
                    DateTime.TryParse(currtime.ToString($"yyyy-MM-dd {rule?.StartTime}"), out var standardStartTime);
                    var currentUserSwRecord = swUserRecord?.FirstOrDefault(c => c.Key == user.UserName).Value?.OrderBy(c => c.AttendanceTime);
                    if (currentUserSwRecord?.FirstOrDefault()?.AttendanceTime > standardStartTime)
                    {
                        // 大于规则设置的打卡时间视为迟到（前提条件是12：00之前 打卡的记录）
                        _item.LateOrleaveEarly++;
                        result.Morning.LateTotal++;
                    }

                    DateTime.TryParse(currtime.ToString($"yyyy-MM-dd {rule?.EndTime}"), out var standardEndTime);
                    var currentUserXwRecord = xwUserRecord?.FirstOrDefault(c => c.Key == user.UserName).Value?.OrderBy(c => c.AttendanceTime);
                    if (currentUserXwRecord?.LastOrDefault()?.AttendanceTime < standardEndTime)
                    {
                        // 早退
                        _item2.LateOrleaveEarly++;
                        result.Night.LateTotal++;
                    }
                }

                _item.PunchRate = _item.Total == 0 ? "0.0" : (Convert.ToDouble((_item.PuncherTotal / Convert.ToDouble(_item.Total)).ToString("F3") ?? "0") * 100).ToString("F1");
                result.Morning.RecordDetails.Add(_item);

                _item2.PunchRate = _item2.Total == 0 ? "0.0" : (Convert.ToDouble((_item2.PuncherTotal / Convert.ToDouble(_item2.Total)).ToString("F3") ?? "0") * 100).ToString("F1");
                result.Night.RecordDetails.Add(_item2);
            }

            result.Night.PunchRate = result.Morning.RecordDetails.Sum(c => c.Total) == 0 ? "0.0" : (Convert.ToDouble((result.Morning.RecordDetails.Sum(c => c.PuncherTotal) / Convert.ToDouble(result.Morning.RecordDetails.Sum(c => c.Total))).ToString("F3") ?? "0") * 100).ToString("F1");
            result.Morning.PunchRate = result.Night.RecordDetails.Sum(c => c.Total) == 0 ? "0.0" : (Convert.ToDouble((result.Night.RecordDetails.Sum(c => c.PuncherTotal) / Convert.ToDouble(result.Night.RecordDetails.Sum(c => c.Total))).ToString("F3") ?? "0") * 100).ToString("F1");

            return result;
        }

        private void GetTopOrganInfo(List<SysOrganization> orgData, SysOrganization currentOrg, ref SysOrganization org)
        {
            var parentOrg = orgData.FirstOrDefault(c => c.Id == currentOrg.ParentId);
            if (parentOrg != null)
            {
                GetTopOrganInfo(orgData, parentOrg, ref org);
            }
            else
            {
                org = currentOrg;
            }
        }

        private void GetChildOrganInfo(List<SysOrganization> orgData, Guid orgId, ref List<SysOrganization> orgs)
        {
            var childOrgs = orgData.Where(c => c.ParentId == orgId)?.ToList();
            if (childOrgs != null && childOrgs.Any())
            {
                if (orgs == null)
                {
                    orgs = new List<SysOrganization>();
                }

                orgs.AddRange(childOrgs);

                foreach (var item in childOrgs)
                {
                    GetChildOrganInfo(orgData, item.Id, ref orgs);
                }
            }
        }

        /// <summary>
        /// 首页考勤统计情况
        /// </summary>
        /// <param name="input"></param>
        /// <returns></returns>
        public async Task<MoveStaffAttendanceRecordStatisticsCurrentDayOutputModel> GetStaffAttendanceRecordCurrentDayStatistics()
        {
            var result = new MoveStaffAttendanceRecordStatisticsCurrentDayOutputModel();
            var currentDayStaffAttendanceRecord = await GetMoveStaffAttendanceRecordStatisticsByDay(DateTime.Now);
            result.NoPuncherTotal = currentDayStaffAttendanceRecord.NoPuncherTotal;
            result.PuncherTotal = currentDayStaffAttendanceRecord.PuncherTotal;
            var currentMonthStartTime = DateTime.Parse($"{DateTime.Now.Year}-{(DateTime.Now.Month).ToString().PadLeft(2, '0')}-01");
            var currentDays = (DateTime.Now - DateTime.Parse($"{DateTime.Now.Year}-{(DateTime.Now.Month).ToString().PadLeft(2, '0')}-01")).Days;
            var puncherTotal = 0; //实际有效打卡
            var puncherUserNumber = 0; //当月应出勤总数
            if (currentDays > 0)
            {
                for (var i = 1; i <= currentDays; i++)
                {
                    var currentDayStaffAttendanceRecord2 = await GetMoveStaffAttendanceRecordStatisticsByDay(DateTime.Parse($"{DateTime.Now.Year}-{(DateTime.Now.Month).ToString().PadLeft(2, '0')}-{(i).ToString().PadLeft(2, '0')}"));
                    puncherTotal += currentDayStaffAttendanceRecord2.PuncherTotal;
                    puncherUserNumber += currentDayStaffAttendanceRecord2.PuncherUserNumber;
                }
            }

            puncherUserNumber += currentDayStaffAttendanceRecord.PuncherUserNumber;
            puncherTotal += currentDayStaffAttendanceRecord.PuncherTotal;

            result.PunchRate = puncherUserNumber == 0 ? "0.0" : (Convert.ToDouble((puncherTotal / Convert.ToDouble(puncherUserNumber)).ToString("F3") ?? "0") * 100).ToString("F1");

            return result;
        }


        private async Task<MoveStaffAttendanceRecordStatisticsDayOutputModel> GetMoveStaffAttendanceRecordStatisticsByDay(DateTime dt)
        {
            var result = new MoveStaffAttendanceRecordStatisticsDayOutputModel();
            DateTime currtime = DateTime.Parse($"{dt.Year}-{(dt.Month).ToString().PadLeft(2, '0')}-{(dt.Day).ToString().PadLeft(2, '0')}");
            int week = (int)currtime.DayOfWeek;
            DateTime.TryParse(currtime.ToString("yyyy-MM-dd 00:00:00"), out var startTime);
            DateTime.TryParse(currtime.ToString("yyyy-MM-dd 23:59:59"), out var endTime);
            //当天打卡记录
            var staffAttendanceRecordQuery = from c in _context.Set<AttendanceRecord>()
                                             where c.AttendanceTime >= startTime && c.AttendanceTime <= endTime
                                             select new
                                             {
                                                 c.AttendanceTime,
                                                 c.UserId,
                                                 c.AttendanceType,
                                                 c.UserNumber
                                             };
            var staffAttendanceRecord = await staffAttendanceRecordQuery.ToListAsync();

            var ruleQuery = from c in _context.Set<StaffAttendanceRule>()
                            join a in _context.Set<StaffAttendanceUser>() on c.Id equals a.StaffAttendanceRuleId into tp2
                            from tu in tp2.DefaultIfEmpty()
                            join b in _context.Set<StaffAttendanceCycle>() on c.Id equals b.StaffAttendanceRuleId into tp
                            from tc in tp
                            where tc.PeriodType == week
                            select new
                            {
                                c.Id,
                                c.IsExcludingLegalHolidays,
                                c.StartTime,
                                c.EndTime,
                                c.Name,
                                User = tu,
                                Cycle = tc,
                            };
            var ruleAll = await ruleQuery.ToListAsync();
            // 当天应考勤的人数
            var currentRuleAll = ruleAll.GroupBy(c => new { c.Id, c.EndTime, c.StartTime, c.IsExcludingLegalHolidays, c.Name }).Select(p => new { Id = p.Key.Id, EndTime = p.Key.EndTime, StartTime = p.Key.StartTime, IsExcludingLegalHolidays = p.Key.IsExcludingLegalHolidays, Name = p.Key.Name, Users = p.Where(c => c.Id == p.Key.Id)?.Select(c => c.User), Cycles = p.Where(c => c.Id == p.Key.Id)?.Select(c => c.Cycle) });
            var currentAttendanceUserIds = currentRuleAll.SelectMany(c => c.Users)?.Select(c => c.UserId);
            if (currentAttendanceUserIds == null)
            {
                return result;
            }
            result.PuncherUserNumber = currentAttendanceUserIds.Count();
            var sysusers = await _context.Set<SysUser>().Where(c => currentAttendanceUserIds.Contains(c.Id)).ToListAsync();
            foreach (var user in sysusers)
            {
                var rule = currentRuleAll?.FirstOrDefault(c => c.Users.Any(p => p.UserId == user.Id));
                DateTime.TryParse(currtime.ToString($"yyyy-MM-dd {rule?.StartTime}"), out var standardStartTime);
                DateTime.TryParse(currtime.ToString($"yyyy-MM-dd {rule?.EndTime}"), out var standardEndTime);
                var currentUserRecord = staffAttendanceRecord?.Where(c => c.UserNumber == user.UserName).OrderBy(c => c.AttendanceTime);
                if (currentUserRecord != null && currentUserRecord.Any())
                {
                    var _firstDate = currentUserRecord.FirstOrDefault()?.AttendanceTime;
                    var _lastDate = currentUserRecord.LastOrDefault()?.AttendanceTime;
                    if (standardStartTime >= _firstDate && _lastDate >= standardEndTime)
                    {
                        // 有效打卡
                        result.PuncherTotal++;
                    }
                    else
                    {
                        // 无效打卡（迟到、早退）
                    }
                }
                else
                {
                    result.NoPuncherTotal++;
                }
            }

            return result;
        }





        public async Task<byte[]> GenerateExcel(bool isChildrens,int month)
        {
            byte[] result = null;
            // 创建一个新的Excel包
            using (var package = new ExcelPackage())
            {
                // 添加一个工作表
                var worksheet = package.Workbook.Worksheets.Add("Sheet1");

                // 创建数据
                var data = new List<List<object>>
            {
               new List<object> {"姓名", "实际出勤天数" },
            };

                var date = DateTime.Now;
                var year = date.Year; 
                var days = DateTime.DaysInMonth(year, month);

                var startDate = DateTime.Parse($"{year}-{month}-01 00:00:01");
                var v = $"{year}-{month}-{$"{DateTime.DaysInMonth(year, month)}".PadLeft(2, '0')} 23:59:59";
                var endDate = DateTime.Parse(v.Trim());

                for (var i = 1; i <= days; i++)
                {
                    DateTime currtime = DateTime.Parse($"{year}-{(month).ToString().PadLeft(2, '0')}-{i.ToString().PadLeft(2, '0')}");
                    string dayOfWeek = currtime.DayOfWeek.ToString();
                    var dayStr = i.ToString();
                    if (dayOfWeek == "Saturday")
                    {
                        dayStr = i + "(周六)";
                    }
                    if (dayOfWeek == "Sunday")
                    {
                        dayStr = i + "(周日)";
                    }
                    data[0].Add(dayStr);

                }

                if (isChildrens)
                {
                    var attList = _context.Set<AttendanceRecord>().Where(x => x.AttendanceType == 2 && x.AttendanceTime >= startDate && x.AttendanceTime <= endDate).OrderBy(x => x.AttendanceTime).ToList();
                    var childrensQuery = await OrganizationFilter(_context.Set<Childrens>().AsQueryable());
                    var childrensList = await childrensQuery.ToListAsync();
                    foreach (var item in childrensList)
                    {
                        var s = new List<object>();
                        s.Add(item.Name);
                        var count = attList.Where(x => x.UserNumber == item.StudentNumber).GroupBy(x => x.AttendanceTime.ToString("yyyy-MM-dd")).Count();
                        s.Add(count);
                        for (var i = 1; i <= days; i++)
                        {
                            DateTime currtime = DateTime.Parse($"{year}-{(month).ToString().PadLeft(2, '0')}-{i.ToString().PadLeft(2, '0')}");
                            var cdate = $"{currtime.ToString("yyyy-MM-dd")}";
                            var attTimeList = attList.Where(x => x.UserNumber == item.StudentNumber && cdate == x.AttendanceTime.ToString("yyyy-MM-dd")).ToList();
                            var AM = "";
                            var PM = "";
                            if (attTimeList.Count > 0)
                            {
                                var first = attTimeList.OrderBy(x => x.AttendanceTime).FirstOrDefault()?.AttendanceTime;
                                var last = attTimeList.OrderByDescending(x => x.AttendanceTime).FirstOrDefault()?.AttendanceTime;
                                //上午打卡  12:00:00之前
                                DateTime.TryParse(currtime.ToString("yyyy-MM-dd 12:00:00"), out var shangwu);
                                //下午打卡  12：00之后23:59:59之前
                                DateTime.TryParse(currtime.ToString("yyyy-MM-dd 23:59:59"), out var xiawu);

                                AM = first < shangwu ? first.Value.ToString("HH:mm:ss") : "";
                                PM = last > shangwu ? last.Value.ToString("HH:mm:ss") : "";
                            }
                            s.Add(AM + "|" + PM);
                        }

                        data.Add(s);
                    }
                }
                else
                {
                    var attList = _context.Set<AttendanceRecord>().Where(x => x.AttendanceType == 1 && x.AttendanceTime >= startDate && x.AttendanceTime <= endDate).OrderBy(x => x.AttendanceTime).ToList();
                    var userQuery = await OrganizationFilter(_context.Set<SysUser>().AsQueryable());
                    var userList = await userQuery.ToListAsync();
                    foreach (var item in userList)
                    {
                        var s = new List<object>();
                        s.Add(item.Name);
                        var count = attList.Where(x => x.UserNumber == item.UserName).GroupBy(x => x.AttendanceTime.ToString("yyyy-MM-dd")).Count();
                        s.Add(count);
                        for (var i = 1; i <= days; i++)
                        {
                            DateTime currtime = DateTime.Parse($"{year}-{(month).ToString().PadLeft(2, '0')}-{i.ToString().PadLeft(2, '0')}");
                            var cdate = $"{currtime.ToString("yyyy-MM-dd")}";
                            var attTimeList = attList.Where(x => x.UserNumber == item.UserName && cdate == x.AttendanceTime.ToString("yyyy-MM-dd")).ToList();
                            var AM = "";
                            var PM = "";
                            if (attTimeList.Count > 0)
                            {
                                var first = attTimeList.OrderBy(x => x.AttendanceTime).FirstOrDefault()?.AttendanceTime;
                                var last = attTimeList.OrderByDescending(x => x.AttendanceTime).FirstOrDefault()?.AttendanceTime;
                                //上午打卡  12:00:00之前
                                DateTime.TryParse(currtime.ToString("yyyy-MM-dd 12:00:00"), out var shangwu);
                                //下午打卡  12：00之后23:59:59之前
                                DateTime.TryParse(currtime.ToString("yyyy-MM-dd 23:59:59"), out var xiawu);

                                AM = first < shangwu ? first.Value.ToString("HH:mm:ss") : "";
                                PM = last > shangwu ? last.Value.ToString("HH:mm:ss") : "";
                            }
                            s.Add(AM + "|" + PM);
                        }

                        data.Add(s);
                    }
                }

                // 将数据写入工作表
                int row = 1;
                foreach (var rowData in data)
                {

                    int col = 1;
                    foreach (var cellData in rowData)
                    {
                        if (cellData.ToString().IndexOf('|') > 0)
                        {
                            var shangwu = cellData.ToString().Split('|')[0];
                            var xiawu = cellData.ToString().Split('|')[1];
                            string multiLineText = shangwu + Environment.NewLine + xiawu;

                            multiLineText = multiLineText.Replace("|", "");
                            worksheet.Cells[row, col].Value = multiLineText;
                        }
                        else
                        {
                            var text = cellData.ToString().Replace("|", "");
                            worksheet.Cells[row, col].Value = text;
                        }
                        worksheet.Cells[row, col].Style.Font.Size = 12;
                        worksheet.Cells[row, col].Style.WrapText = true;
                        worksheet.Cells[row, col].Style.HorizontalAlignment = ExcelHorizontalAlignment.Center;
                        worksheet.Cells[1, col].Style.Font.Bold = true;
                        col++;
                    }
                    row++;
                }
                result = package.GetAsByteArray();
            }
            return result;
        }


        public async Task<byte[]> AttendanceRecordExcelModel(int month)
        {
            return await GenerateExcel(false, month);

        }

        public async Task<byte[]> AttendanceChildrensRecordExcelModel(int month)
        {
            return await GenerateExcel(true, month);

        }
    }
}
